package br.pucrio.inf.les.SPLAnalyser.core;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.core.resources.IProject;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.compare.diff.merge.service.MergeService;
import org.eclipse.emf.compare.diff.metamodel.ComparisonResourceSnapshot;
import org.eclipse.emf.compare.diff.metamodel.DiffElement;
import org.eclipse.emf.compare.diff.metamodel.DiffFactory;
import org.eclipse.emf.compare.diff.metamodel.DiffModel;
import org.eclipse.emf.compare.diff.service.DiffService;
import org.eclipse.emf.compare.match.metamodel.MatchModel;
import org.eclipse.emf.compare.match.service.MatchService;
import org.eclipse.emf.compare.util.ModelUtils;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.emf.ecore.xmi.XMLResource;

import br.pucrio.inf.les.SPLAnalyser.core.models.impactanalysismodel.ImpactAnalysisModel;
import br.pucrio.inf.les.genarch.GenarchEMFPlugin;

public class SquidAnalyserFacade {
	Extractor extractor;
	ImpactAnalysisModel analysisModel;
	IProject projectTarget;
	Object queryModel;
	SourceCodeAnalyser sourceCodeAnalyser;
	String analysisModelPath;
	String queryModelPath;
	
	
	public SquidAnalyserFacade(IProject projectTarget, Extractor extractorImpl, SourceCodeAnalyser sourceCodeAnalyserImpl){
		this.projectTarget = projectTarget;
		this.extractor = extractorImpl;
		this.sourceCodeAnalyser = sourceCodeAnalyserImpl;
	}
	
	public void runSquidAnalyser(){
		analysisModel = extractor.runExtractor(projectTarget);
		analysisModel = sourceCodeAnalyser.runCodeAnalyser(projectTarget, analysisModel);
		saveModel(analysisModel, extractor.getPath());
	}
	
	public void executeQuery(Query query, Visualizer visualize){
		queryModel = query.runQuery( loadAnalysisModel() );
		visualize.runVisualize(queryModel, query.getName(), projectTarget.getFullPath().toString());
	}
	
	private void saveModel(ImpactAnalysisModel model,String path){
		Map options = new HashMap();
		options.put(XMLResource.OPTION_ENCODING, "UTF-8");		
		
		URI modelFileURI = URI.createPlatformResourceURI(path, false);	
		
		ResourceSet analysisModelResourceSet = new ResourceSetImpl();
		Resource impactAnalysisResource = analysisModelResourceSet.createResource(modelFileURI);
		
		impactAnalysisResource.getContents().add(model);

		try {
			impactAnalysisResource.save(options);
		} catch (IOException e) {						
			e.printStackTrace();
			GenarchEMFPlugin.INSTANCE.log(e);
		}	
	}
	
	public ImpactAnalysisModel getAnalysisModel(){
		return analysisModel;
	}
	
	private ImpactAnalysisModel loadAnalysisModel(){
		URI analysisModelFileURI = URI.createPlatformResourceURI(extractor.getPath());
		ResourceSet analysisModelResourceSet = new ResourceSetImpl();
		Resource analysisModelResource = analysisModelResourceSet.getResource(analysisModelFileURI,true);
		ImpactAnalysisModel model = (ImpactAnalysisModel)analysisModelResource.getContents().get(0);
		
		
		
		
		
		
		
//		// Creates the resourceSets where we'll load the models
//		final ResourceSet resourceSet1 = new ResourceSetImpl();
//		final ResourceSet resourceSet2 = new ResourceSetImpl();
//		// Register additionnal packages here. For UML2 for instance :
//		// Resource.Factory.Registry.INSTANCE.getExtensionToFactoryMap().put(UMLResource.FILE_EXTENSION,
//		// UMLResource.Factory.INSTANCE);
//		// resourceSet1.getPackageRegistry().put(UMLPackage.eNS_URI, UMLPackage.eINSTANCE);
//		// resourceSet2.getPackageRegistry().put(UMLPackage.eNS_URI, UMLPackage.eINSTANCE);
//
//		try {
//			System.out.println("Loading resources.\n"); //$NON-NLS-1$
//			// Loads the two models passed as arguments
////			URI analysisModelFileURI1 = URI.createPlatformResourceURI("/MobileMedia04_OO/ImpactAnalysis/ImpactAnalysisModel.impactanalysismodel");
////			Resource analysisModelResource = resourceSet1.getResource(analysisModelFileURI1,true);
//			File file = new File("/MobileMedia04_OO/ImpactAnalysis/CalculadoraExemplo.javaast");
//			final EObject model1 = ModelUtils.load(file, resourceSet1);
//			
//			
////			URI analysisModelFileURI2 = URI.createPlatformResourceURI("/MobileMedia04_OO/ImpactAnalysis/ImpactAnalysisModel2.impactanalysismodel");
//			File file2 = new File("/MobileMedia04_OO/ImpactAnalysis/CalculadoraExemplo2.javaast");
//			final EObject model2 = ModelUtils.load(file2, resourceSet2);
//
//			// Creates the match then the diff model for those two models
//			System.out.println("Matching models.\n"); //$NON-NLS-1$
//			final MatchModel match = MatchService.doMatch(model1, model2,
//					Collections.<String, Object> emptyMap());
//			System.out.println("Differencing models.\n"); //$NON-NLS-1$
//			final DiffModel diff = DiffService.doDiff(match, false);
//
//			System.out.println("Merging difference to args[1].\n"); //$NON-NLS-1$
//			final List<DiffElement> differences = new ArrayList<DiffElement>(diff.getOwnedElements());
//			// This will merge all references to the right model (second argument).
//			diff.getDifferences();
//			
//			// Prints the results
////			try {
////				System.out.println("MatchModel :\n"); //$NON-NLS-1$
//////				System.out.println(ModelUtils.serialize(match));
////				System.out.println("DiffModel :\n"); //$NON-NLS-1$
//////				System.out.println(ModelUtils.serialize(diff));
////			} catch (final IOException e) {
////				e.printStackTrace();
////			}
//
//			// Serializes the result as "result.emfdiff" in the directory this class has been called from.
//			System.out.println("saving emfdiff as \"result.emfdiff\""); //$NON-NLS-1$
//			final ComparisonResourceSnapshot snapshot = DiffFactory.eINSTANCE
//					.createComparisonResourceSnapshot();
//			snapshot.setDate(Calendar.getInstance().getTime());
//			snapshot.setMatch(match);
//			snapshot.setDiff(diff);
//			ModelUtils.save(snapshot, "/MobileMedia04_OO/ImpactAnalysis/result.emfdiff"); //$NON-NLS-1$
//		} catch (final IOException e) {
//			// shouldn't be thrown
//			e.printStackTrace();
//		} catch (final InterruptedException e) {
//			e.printStackTrace();
//		}
	
		
		
		
		
		
		return model;
	}
	
}
